﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Gueei.Gallery.Core.DisplayProfiles;
using Gueei.Gallery.Core.Entities;
using Gueei.Gallery.Core.Filters;
using Gueei.Gallery.Core.Repositories;

namespace Gueei.Gallery.Core.Services
{
	public class DefaultImageService: IImageService
	{
		private readonly IImageRepository _imageRepo;
		private readonly IFileRepository _fileRepo;
		private readonly ITagRepository _tagRepo;

		public DefaultImageService(IImageRepository imageRepo, IFileRepository fileRepo, ITagRepository tagRepo)
		{
			_imageRepo = imageRepo;
			_fileRepo = fileRepo;
			_tagRepo = tagRepo;
		}

		public Entities.Image SaveNewImage(string tags, string name, string description, string originalFileName, 
			string mimeType, Entities.User creator, byte[] data)
		{
			if (!Image.IsImageType(mimeType))
				throw new ArgumentException("Supplied mimeType is not supported");

			var newId = Guid.NewGuid();
			if (!_fileRepo.SaveFile(newId, data, false))
				throw new Exception("Unknown error occurred while saving new image");

			var tagList = tags == null ? _tagRepo.CreateOrReturnTags(new string[0]) : _tagRepo.CreateOrReturnTags(tags.Split(','));

			var newImage = new Image(mimeType)
			               	{
			               		Id = newId,
			               		Name = name,
			               		Description = description,
			               		CreateDate = DateTime.Now,
			               		Creator = creator,
			               		Tags = tagList,
			               		OriginalFileName = originalFileName,
			               		LastModified = DateTime.Now
			               	};

			// Change the count in the related tag
			foreach(var t in tagList)
			{
				t.ItemCount++;
				_tagRepo.SaveTag(t);
			}

			return _imageRepo.SaveImage(newImage, false);
		}

		public byte[] GetImageFile(Guid id)
		{
			return _fileRepo.RetriveFile(id);
		}


		public Image GetImage(Guid id)
		{
			return _imageRepo.GetImage(id);
		}


		public bool ImageExists(Guid id)
		{
			return _imageRepo.ImageExists(id);
		}

		public byte[] GetImageFile(Guid id, DisplayProfileBase profile)
		{
			return profile.ConvertImage(GetImageFile(id), GetImage(id).MimeType);
		}

		public Image SaveNewImage(string tags, string name, string description, string originalFileName, string mimeType, User creator, System.IO.FileInfo file)
		{
			var data = new byte[file.Length];
			using(var fs = file.OpenRead())
			{
				fs.Read(data, 0, (int)file.Length);
			}
			return SaveNewImage(tags, name, description, originalFileName, mimeType, creator, data);
		}


		public Image UpdateImage(Guid id, string tags, string name, string description, User modifiedBy)
		{
			if (!ImageExists(id))
			{
				throw new ArgumentException("Supplied Image is not existed in db");
			}
			var image = GetImage(id);
			foreach (var t in image.Tags)
			{
				t.ItemCount--;
				_tagRepo.SaveTag(t);
			}

			image.Name = name;
			image.Description = description;
			image.ModifiedBy = modifiedBy;

			var tagList = tags == null ? 
				_tagRepo.CreateOrReturnTags(new string[0]) : 
				_tagRepo.CreateOrReturnTags(tags.Split(','));

			foreach(var t in tagList)
			{
				t.ItemCount++;
				_tagRepo.SaveTag(t);
			}

			image.Tags = tagList;
			image.LastModified = DateTime.Now;
			return _imageRepo.SaveImage(image, true);
		}


		public Image ApplyFilterAndSaveImage(Guid id, Filters.ImageFilter filter)
		{
			if (!ImageExists(id))
			{
				throw new ArgumentException("Supplied Image is not existed in db");
			}
			Image image = GetImage(id);
			using (var originalImage = ImageFilter.CreateBitmapImageFromByteArray(GetImageFile(id)))
			{
				using (var img = filter.ApplyFilter(originalImage))
				{
					_fileRepo.SaveFile(id, ImageFilter.CreateByteArrayFromBitmapImage(img), true);
				}
			}
			image.LastModified = DateTime.Now;
			return _imageRepo.SaveImage(image, true);
		}
	}
}
